package com.example.websocket.server;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;

import javax.websocket.*;
import javax.websocket.server.PathParam;
import javax.websocket.server.ServerEndpoint;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Logger;

@ServerEndpoint("/webserver/{username}")
@Component
public class WebSocketServer {

    private Logger logger = Logger.getLogger("com.example.websocket.server");

    // 当前在线人数
    private static int onlineCount = 0;

    // 用来存放每个客户端对应的websocket对象
    private static ConcurrentHashMap<String, WebSocketServer> webSocketMap = new ConcurrentHashMap<>();

    // 每个客户端的连接会话，需要通过它来给客户端发送数据
    private Session session;

    // 用户名称
    private String username = "";

    /*
        建立连接
     */
    @OnOpen
    public void onOpen(Session session, @PathParam("username") String username){
        this.session = session;
        this.username = username;
        // 在线人数+1
        addOnlineCount();
        logger.info("用户连接: " + username + "当前在线人数为: " + getOnlineCount());
        try {
            // messageType 1代表上线、2代表下线、3代表在线名单、4代表普通消息
            // 通知所有人当前用户上线
            Map<String ,Object> msg = new HashMap<>();
            msg.put("messageType",1);
            msg.put("username",username);
            sendMessageAll(JSON.toJSONString(msg),username);

            // 将当前用户添加到map集合中
            webSocketMap.put(username, this);

            // 向自己发送消息，查看当前在线用户
            Map<String, Object> msg2 = new HashMap<>();
            msg2.put("messageType",3);
            // 移除当前用户
            Set<String> set = webSocketMap.keySet();
            msg2.put("onlineUsers", set);
            sendMessageTo(JSON.toJSONString(msg2),username);
        }
        catch (Exception e){
            logger.warning("用户: " + username + ",网络异常!!");
        }
    }


    /*
        关闭连接
     */
    @OnClose
    public void onClose(){
        if(webSocketMap.containsKey(username)){
            // 从socket集合中删除
            webSocketMap.remove(username);
            // 在线人数-1
            subOnlineCount();
            try{
                // messageType 1代表上线、2代表下线、3代表在线名单、4代表普通消息
                Map<String,Object> map1 = new HashMap<>();
                map1.put("messageType",2);
                map1.put("onlineUsers",webSocketMap.keySet());
                map1.put("username",username);
                // 告诉所有人当前用户下线了
                sendMessageAll(JSON.toJSONString(map1),username);
            }
            catch (Exception e){
                logger.info(username + "下线时通知所有人发生了错误");
            }
        }
        logger.warning("用户: " + username + " 退出, 当前在线人数为: " + getOnlineCount());
    }

    /*
        收到客户端的消息
     */
    @OnMessage
    public void onMessage(String message, Session session){
        try{
            logger.info(username + "用户消息: " + ",消息: " + message);
            // 将接收到的消息进行转换
            JSONObject jsonObject = JSON.parseObject(message);
            // 获取消息内的信息
            String textMessgae = jsonObject.getString("message");
            String formUsername = jsonObject.getString("username");
            String toUsername = jsonObject.getString("to");

            // messageType 1代表上线、2代表下线、3代表在线名单、4代表普通消息
            Map<String,Object> map1 = new HashMap<>();
            map1.put("messageType",4);
            map1.put("textMessage",textMessgae);
            map1.put("fromUsername",formUsername);
            // 如果不是发给所有人，那么就发给目标用户
            if(toUsername.equals("All")){
                map1.put("toUsername","所有人");
                sendMessageAll(JSON.toJSONString(map1),formUsername);
            }
            else{
                map1.put("toUsername",toUsername);
                sendMessageTo(JSON.toJSONString(map1), toUsername);
            }
        }
        catch (Exception e){
            logger.info("系统错误");
        }
    }

    @OnError
    public void onError(Session session, Throwable error){
        logger.info("服务器错误,原因: " + error.getMessage());
        error.printStackTrace();
    }

    public void sendMessageTo(String message, String toUsername) {
        // 向目标用户发送消息
        for (WebSocketServer item : webSocketMap.values()) {
            if(item.username.equals(toUsername)){
                item.session.getAsyncRemote().sendText(message);
                break;
            }
        }
    }

    public void sendMessageAll(String message, String fromUsername) {
        // 向所有人发送消息
        for (WebSocketServer item : webSocketMap.values()) {
            item.session.getAsyncRemote().sendText(message);
        }

    }

    private static synchronized int getOnlineCount() {
        return onlineCount;
    }

    private static synchronized  void subOnlineCount() {
        WebSocketServer.onlineCount--;
    }

    private static synchronized  void addOnlineCount() {
        WebSocketServer.onlineCount++;
    }
}
